/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/

/* A short program to demonstrate/test SimpleSockets.

   When only a port number is given (in addition to the keyword "tcp" or "udp"),
   the program runs in the listening mode and prints the messages it receives.
   
   When given two extra arguments, the program reads lines from stdin and sends
   them to the given host and port.

   To compile on Linux: gcc simplesocketsdemo.c ../simplesockets.c -o ssdemo

   To compile on Windows: cl simplesocketsdemo.c ..\simplesockets.c ws2_32.lib
   (or if using an IDE, make sure the library ws2_32.lib is compiled in)

*/

#include <stdlib.h>

#include "../simplesockets.h"


#define usage() { fprintf(stderr, "Usage: %s ( tcp | udp ) (<listenport> | <remotehost> <remoteport>)\n", argv[0]); return 1; }


#define TCPMODE 0
#define UDPMODE 1
#define LISTEN 2

int main(int argc, char *argv[]) {
    SOCKET s, ls;
    char *host;
    int port;
    int mode, len;
    char buf[1024];

    // process arguments
    if (argc < 3 || argc > 4) usage();

    if (strcmp(argv[1], "tcp") == 0) mode = TCPMODE;
    else if (strcmp(argv[1], "udp") == 0) mode = UDPMODE;
    else usage();

    if (argc == 3) {
        mode |= LISTEN;
        port = atoi(argv[2]);
    }
    else {
        host = argv[2];
        port = atoi(argv[3]);
    }

    if (port == 0) usage();

    // initialize SimpleSockets
    ss_init();
    
    switch (mode) {
        // sending TCP mode: connect, read lines & send them
        case TCPMODE:
            s = ss_connect(host, port);
            if (s != INVALID_SOCKET) {
                while (fgets(buf, sizeof(buf), stdin)) {
                    if (ss_send(s, buf, strlen(buf)) == 0) break;
                }
            }
            break;

        // sending UDP mode: resolve the hostname, read lines & send them
        case UDPMODE:
            s = ss_udpsocket(port+1);
            if (s != INVALID_SOCKET) {
                struct sockaddr_in sa;

                if (ss_createsockaddr(&sa, host, port) == 0) {
                    fprintf(stderr, "host %s not found\n", host);
                }
                else {
                    while (fgets(buf, sizeof(buf), stdin)) {
                        if (ss_udpsend(s, &sa, buf, strlen(buf)) == 0) break;
                    }
                }
            }
            break;

        // listening TCP mode: create a listening socket, accept a connection, print received data
        case TCPMODE | LISTEN:
            ls = ss_listen(port);
            if (ls != INVALID_SOCKET) {
                struct sockaddr_in sa;
                
                s = ss_accept(ls, &sa);
                if (s != INVALID_SOCKET) {
                    unsigned char *ip = (unsigned char *) &sa.sin_addr;
                    printf("Accepted connection from %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);

                    while ((len = ss_receive(s, buf, sizeof(buf))) > 0) {
                        fwrite(buf, 1, len, stdout);
                    }
                }
            }
            break;

        // listening UDP mode: create a UDP socket, print received datagrams
        case UDPMODE | LISTEN:
            s = ss_udpsocket(port);
            if (s != INVALID_SOCKET) {
                struct sockaddr_in sa;
                unsigned char *ip = (unsigned char *) &sa.sin_addr;

                while ((len = ss_udpreceive(s, &sa, buf, sizeof(buf))) > 0) {
                    printf("Datagram from %d.%d.%d.%d:\n", ip[0], ip[1], ip[2], ip[3]);
                    fwrite(buf, 1, len, stdout);
                }
            }

            break;

    }

    ss_deinit();

    return 0;
}


